package kr.pe.johnkim.sendme.activity;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import kr.pe.johnkim.sendme.provider.SendMeLog;
import kr.pe.johnkim.sendme.provider.SendMeVoice;
import kr.pe.johnkim.sendme.rest.SendMeAudioMessageRest;
import kr.pe.johnkim.sendme.rest.SendMeLogRest;
import kr.pe.johnkim.sendme.util.SendMeActivityManager;
import kr.pe.johnkim.sendme.util.SendMeCommon;
import kr.pe.johnkim.sendme.util.SendMeConstant;
import kr.pe.johnkim.sendme.util.SendMeCustomTimePickerDialog;
import kr.pe.johnkim.sendme.util.SendMeDBManagerAudioRecord;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

/**
 * 음성 메시지 예약 발송 액티비티 클래스이다.
 *  제목, 날짜, 시간 등을 선택하고 전송한다.
 *  그 외 필요한 파라미터들은 전달받은 값을 사용한다.
 *  
 *  부모 액티비티에게 결과를 날려주어야 하므로 상단 메뉴기능은 넣지 않음
 *   아니면 결과 세팅해서 부모까지 종료시키도록해야.
 *  
 * @author blue
 *
 */
public class SendMeAudioSendReservationActivity extends Activity implements OnClickListener{
	public static String TAG = SendMeAudioSendReservationActivity.class.getSimpleName();
	
	// 액티비티 매니저를 가져 온다.
	private SendMeActivityManager sendMeActivityManager = SendMeActivityManager.getInstance();

	String applicationAudioTempDirectory = SendMeConstant.APPLICATION_AUDIO_TEMP_DIRECTORY; 		//"/Android/data/kr.pe.jonhkim.sendme.activity/.AudioRecord/temp";			// 녹음 중인 임시파일 저장될 경로 지정, 탐색기,미디어 스캐너에 나타나지 않게 비공개 처리 

	SimpleDateFormat reservationDateSimpleDateFormat = SendMeConstant.reservationDateSimpleDateFormat;	// 날짜 선택 포맷(출력용)
	SimpleDateFormat reservationTimeSimpleDateFormat = SendMeConstant.reservationTimeSimpleDateFormat;	// 시간 선택 포맷(출력용)
	SimpleDateFormat reservationDateSimpleDateFormatForSend = SendMeConstant.reservationDateSimpleDateFormatForSend;	// 시간 선택 포맷(전송용)
	SimpleDateFormat reservationTimeSimpleDateFormatForSend = SendMeConstant.reservationTimeSimpleDateFormatForSend;	// 시간 선택 포맷(전송용)

	// 파일명
	String fileName;

	// 파일명 포함하는 파일 경로
	String filePath;
	
	// 보내는 사람 전번
	String sender;
	// 받는 사람 전번, 이름
	String[] receiverList ;
	String[] receiverNameList ;
	
	// 예약 전송 관련
	String reservationDate;			// 예약 전송 날짜		
	String reservationTime;			// 예약 전송 시각
	boolean isReservationDateSet;		
	boolean isReservationTimeSet;
	EditText audio_message_reservation_title_txt;
	Button audio_message_reservation_date_btn;		// 예약 날짜 선택
	Button audio_message_reservation_time_btn;		// 예약 시간 선택
	Button audio_message_reservation_send_btn;		// 예약 전송

	Calendar reservationCalendar;				
	DatePickerDialog reservationDatePickerDialog;
	SendMeCustomTimePickerDialog reservationCustomTimePickerDialog;

	
	
	// 데이터 전달용 번들과 인텐트
	Bundle extraBundle;
	Intent resultIntent;
	
	ImageButton imageButtonTopBack;
	ImageButton imageButtonTopMainMenu;
	
	// 프로그래스바(로딩 표시)
	private ProgressDialog dialog;

	
	// 로그를 남긴다
	private static final int THREAD_REGISTER_LOG = 100;
	
	// 음성 메시지 예약 전송전 확인 창을 띄운다
	private static final int THREAD_CONFIRM_RESERVATION_SEND_AUDIO = 107;
	
	// 음성 메시지 예약 화면에서 예약 날짜, 시간을 선택하라는 알림을 띄운다			
	private static final int THREAD_RESERVATION_SEND__TIME_NOT_SELECTED = 115;	


	// 프로그레스 바를 출력 한다.
	private static final int THREAD_PROGRESS_BAR_VISIBLE = 108;

	// 프로그레스 바를 감춘다.
	private static final int THREAD_PROGRESS_BAR_INVISIBLE = 109;


	// 예약 등록 성공 토스트를 띄운다
	private static final int THREAD_TOAST_RESERVATION_SEND_SUCCESS = 111;
	
	// 등록 실패 토스트를 띄운다
	private static final int THREAD_TOAST_SEND_FAIL = 112;		

	private static final int RESULT_MAIN_MENU_CALLED = 600;		

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// 커스텀 타이블 바를 설정 한다.
		Window window = getWindow();
		window.requestFeature(Window.FEATURE_CUSTOM_TITLE);

		setContentView(R.layout.activity_send_me_audio_send_reservation);

		window.setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_bar_03);

		// 액티비티 매니저에 담는다.
		sendMeActivityManager.addActivity(this);
		
		// 내 전화번호 (보낸 사람 전화번호) 획득
		confirmNotification();
		
		
		// 뒤로 가기 화살표 버튼을 설정 한다.
		imageButtonTopBack = (ImageButton)findViewById(R.id.imageButtonTopBack);
		imageButtonTopBack.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub

				// 화면을 닫는다.
				// 취소 역할. 자신만 종료
				setResult(RESULT_CANCELED, resultIntent);
				finishActivity();
				
			}
		});

		// 타이틀바의 메인 메뉴 버튼을 설정 한다.
		imageButtonTopMainMenu = (ImageButton)findViewById(R.id.imageButtonTopMainMenu);
		imageButtonTopMainMenu.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Log.i(TAG, "pressed top main menu.");

				// 메인 메뉴 화면을 출력 한다.
				Intent i = new Intent(SendMeAudioSendReservationActivity.this, SendMeMainMenuActivity.class);
				startActivity(i);
				
				// 화면을 닫는다. 메뉴 콜. 부모도 종료
				setResult(RESULT_MAIN_MENU_CALLED, resultIntent);
				finishActivity();
			}
		});
		
		
		// 전달받은 데이터를 획득
		Intent getIntent = getIntent();
		sender = getIntent.getStringExtra("sender");
		filePath = getIntent.getStringExtra("filePath");
		fileName = getIntent.getStringExtra("fileName");
		receiverList = getIntent.getStringArrayExtra("receiverList");
		receiverNameList = getIntent.getStringArrayExtra("receiverNameList");		

		// 예약 모드 화면에 있는 입력폼
		audio_message_reservation_title_txt = (EditText) findViewById(R.id.audio_message_reservation_title_txt);
		audio_message_reservation_date_btn = (Button) findViewById(R.id.audio_message_reservation_date_btn);
		audio_message_reservation_time_btn = (Button) findViewById(R.id.audio_message_reservation_time_btn);
		audio_message_reservation_send_btn = (Button) findViewById(R.id.audio_message_reservation_send_btn);

		audio_message_reservation_date_btn.setOnClickListener(this);
		audio_message_reservation_time_btn.setOnClickListener(this);
		audio_message_reservation_send_btn.setOnClickListener(this);

		extraBundle = new Bundle();
		resultIntent = new Intent();
		
		
		// 로깅.
		mHandler.sendMessage(mHandler.obtainMessage(THREAD_REGISTER_LOG));
			
		
		initReservationScreen();
	}

	/*
	 * 하단 녹음/메뉴 버튼 클릭 리스너
	 */
	@Override
	public void onClick(View v) {
		switch (v.getId()) {

			// 예약 날짜 선택			
		case R.id.audio_message_reservation_date_btn:		
			selectReservationDate();	
			break;
			// 예약 시간 선택
		case R.id.audio_message_reservation_time_btn:
			selectReservationTime();
			break;
			// 예약 전송 하기
		case R.id.audio_message_reservation_send_btn:
			if(isReservationDateSet&&isReservationTimeSet){
				mHandler.sendMessage(mHandler.obtainMessage(THREAD_CONFIRM_RESERVATION_SEND_AUDIO));		// 확인 후 전송
			}else{
				// 예약 날짜, 시간을 선택해주시기 바랍니다.
				mHandler.sendMessage(mHandler.obtainMessage(THREAD_RESERVATION_SEND__TIME_NOT_SELECTED));		
			}
			break;
		}
	}

	
	
	// 확인창.
	/**
	 * 음성 메시지 예약 전송전 확인 창을 띄운다
	 */
	private Runnable confirmReservationSendAudio = new Runnable() {
		@Override
		public void run() {
			
			String dialogReceiver = "";
			if(receiverNameList.length==1) {
					dialogReceiver = receiverNameList[0]+" 님";	// receiverList --> receiverNameList
			} else {
				dialogReceiver = "그룹";
			}
			new AlertDialog.Builder(SendMeAudioSendReservationActivity.this)
			.setTitle("예약 전송 확인")
			.setMessage(dialogReceiver + "에게 음성 메시지를 예약 전송하시겠습니까?")
			.setNegativeButton("취소", new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {

				}
			})
			.setPositiveButton("확인", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					threadRegisterVoice();	// ### 
				}
			}).show();
			
		}
	};
	/**
	 * 음성 메시지 예약 화면에서 예약 날짜, 시간을 선택하라는 알림을 띄운다		
	 */
	private Runnable reservationSendTimeNotSelected = new Runnable() {
		@Override
		public void run() {
			
			new AlertDialog.Builder(SendMeAudioSendReservationActivity.this)
			.setTitle("예약 발송")
			.setMessage("음성 메시지를 보낼 날짜, 시간을 선택해주시기 바랍니다.")
			.setNegativeButton("", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					
				}
			})
			.setPositiveButton("확인", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					
				}
			}).show();
			
		}
	};
	
	// 토스트
	/**
	 * 음성 메시지 예약 전송에 성공했다는 toast 를 띄운다.
	 */
	public void showToastAudioReservationSendSuccess() {					
		CharSequence text = "메시지가 예약 전송 되었습니다";
		Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
		toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0);
		toast.show();
	}
	/**
	 * 음성 메시지 전송에 실패했다는 toast 를 띄운다.
	 */
	public void showToastAudioSendFail() {
		CharSequence text = "메시지 전송에 실패하였습니다";
		Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
		toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0);
		toast.show();
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 녹음 관련 기능들

	/**
	 * 필요한 핸들러를 등록해서 사용한다.
	 */
	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch(msg.what) {
			
			// 로그를 남긴다
			case THREAD_REGISTER_LOG : 
				threadRegisterLog();
				break;	
				// 음성 메시지 예약 전송전 확인 창을 띄운다
			case THREAD_CONFIRM_RESERVATION_SEND_AUDIO : 
				runOnUiThread(confirmReservationSendAudio);
				break;
				// 음성 메시지 예약 화면에서 예약 날짜, 시간을 선택하라는 알림을 띄운다		
			case THREAD_RESERVATION_SEND__TIME_NOT_SELECTED : 
				runOnUiThread(reservationSendTimeNotSelected);		
				break;
				
				// (서버 통신) 프로그레스 바를 출력 한다.
			case THREAD_PROGRESS_BAR_VISIBLE : 
					dialog.show();
				break;
				// (서버 통신) 프로그레스 바를 감춘다.
			case THREAD_PROGRESS_BAR_INVISIBLE : 
				dialog.dismiss();
				break;
				// (서버 통신) 예약 전송 성공 토스트를 띄운다	
			case THREAD_TOAST_RESERVATION_SEND_SUCCESS : 
				showToastAudioReservationSendSuccess();		
				break;	
				// (서버 통신) 전송 실패 토스트를 띄운다
			case THREAD_TOAST_SEND_FAIL :
				showToastAudioSendFail();
				break;	

			}
		}
	};


	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 예약 관련 기능들

	// 초기화
	public void initReservationScreen(){

		// 예약 날짜, 시간 선택기 초기화
		reservationCalendar = Calendar.getInstance();
		
		
		
		
		//  23시 -> 다음날로.  24시는 없음. 24 -> 0
		if(reservationCalendar.get(Calendar.HOUR_OF_DAY) == 23){
			reservationCalendar.add(Calendar.DAY_OF_MONTH, 1);
		}
		
		reservationDatePickerDialog = new DatePickerDialog(this, reservationDateSetListener, 
				reservationCalendar.get(Calendar.YEAR), 
				reservationCalendar.get(Calendar.MONTH), 
				reservationCalendar.get(Calendar.DAY_OF_MONTH));
		
		
		int nowHour = reservationCalendar.get(Calendar.HOUR_OF_DAY);
		int nowHourPlus = nowHour;
		
		nowHourPlus = nowHourPlus+1;		//
		if(nowHourPlus>23){
			nowHourPlus = nowHourPlus - 24;
		}

		Log.d(TAG,"nowHourPlus:"+nowHourPlus);
		reservationCustomTimePickerDialog = new SendMeCustomTimePickerDialog(this, reservationCustomTimeSetListener, 
//				reservationCalendar.get(nowHourPlus), 		// 제대로 동작하지 않음.
				nowHourPlus, // 
				0,		//reservationCalendar.get(Calendar.MINUTE),  // 초기 값이라면 현재시각이 아닌 0으로 설정 
				false);
		
		// 예약 날짜,시간 선택뷰 초기화
		audio_message_reservation_title_txt.setText("");	// 제목
//		audio_message_reservation_date_btn.setText("날짜 선택");
//		audio_message_reservation_time_btn.setText("시간 선택");
		isReservationDateSet = false;
		isReservationTimeSet = false;

	}
	// 날짜 선택창 호출
	public void selectReservationDate(){
		reservationDatePickerDialog.show();
	}
	// 시간 선택창 호출
	public void selectReservationTime(){
		reservationCustomTimePickerDialog.show();
	}

	// 날짜 선택 리스너
	DatePickerDialog.OnDateSetListener reservationDateSetListener = new DatePickerDialog.OnDateSetListener() {
		@Override
		public void onDateSet(DatePicker view, int year, int monthOfYear,
				int dayOfMonth) {
			// 출력용
			Calendar calendar = GregorianCalendar.getInstance();
			calendar.set(year, monthOfYear, dayOfMonth);
			Date date = calendar.getTime();
			String str = reservationDateSimpleDateFormat.format(date);
			audio_message_reservation_date_btn.setText(str);

			// 전송용
			isReservationDateSet = true;
			reservationDate	= reservationDateSimpleDateFormatForSend.format(date);
		}
	};				

	// 커스텀 시간 선택 리스너
	private SendMeCustomTimePickerDialog.OnTimeSetListener reservationCustomTimeSetListener = new SendMeCustomTimePickerDialog.OnTimeSetListener() {
	    @Override
	    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
			// 출력용
			Calendar calendar = GregorianCalendar.getInstance();
			calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
			calendar.set(Calendar.MINUTE, minute);
			Date date = calendar.getTime();
			String str = reservationTimeSimpleDateFormat.format(date);
			audio_message_reservation_time_btn.setText(str);

			// 전송용
			isReservationTimeSet = true;
			reservationTime = reservationTimeSimpleDateFormatForSend.format(date);
	    }
	};
	
	
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 서버 통신

	/**
	 * 음성 메시지를 등록한다
	 *  일반 리스트를 서버로 전송할때는 서버에서 RequestBody 로 받아서 json을 자동으로 object 변환시켜주므로
	 *    jsonArray 에 jsonObject 를 담을때 toString() 처리하여 담아서 보내야 하지만 
	 *  multipart로 파일을 전송하는 경우에는 서버에서 RequestParam 으로 받는데 이때에는 json을 자동으로 object 변환하지 않기 때문에
	 *   jsonArray 에 jsonObject 를 담을때 jsonObject 그대로 넣어야 서버에서 받을때 넣은 json 형태 그대로 꺼내어진다. 
	 */
	public void threadRegisterVoice() {

		// 프로그레스 바를 출력 한다.
		mHandler.sendMessage(mHandler.obtainMessage(THREAD_PROGRESS_BAR_VISIBLE));

		Thread thread = new Thread(new Runnable() {

			public void run() {
				// TODO Auto-generated method stub
				
				// 받는 사람 리스트를 string 데이터로 변환
				JSONObject jsonObject = null;
				JSONArray jsonArray = new JSONArray();
				String receiverListStr = "";
				try{
					for(int i=0; i<receiverList.length; i++){
						// 방법 1
						jsonObject = new JSONObject();
						jsonObject.put("phoneNumber", receiverList[i]);
//						jsonArray.put(jsonObject.toString());			// 서버로 전송 실패하게 됨
						jsonArray.put(jsonObject);						
					}
					receiverListStr = jsonArray.toString();
					Log.d(TAG,"receiverListStr:"+receiverListStr);		
				}catch(Exception e){
					e.printStackTrace();
				}
				
				SendMeCommon sendMeCommon = new SendMeCommon();

				SendMeVoice sendMeVoice = new SendMeVoice();
				sendMeVoice.setIdSendMeVoice("");			// 테이블 아이디.(PK)	

				sendMeVoice.setSender(sender);		//	생성자. 보내는 멤버 휴대 전화 번호.	
				sendMeVoice.setReceiver(receiverListStr);		// 받는 멤버 휴대 전화 번호.		 

				sendMeVoice.setActivateYn("Y");				// 활성화 여부.	
				sendMeVoice.setModifyDate(sendMeCommon.getCurrentDate());				// 수정 일자.	
				sendMeVoice.setRegisterDate(sendMeCommon.getCurrentDate());				// 등록 일자.	

				sendMeVoice.setAvailableDay(SendMeConstant.AVAILABLE_DAY);			// 사용 가능 기간 일수. 기본값은 7	
				sendMeVoice.setReadYn("N");					// 읽음 여부. 기본값은 N			

				// 예약 발송
				sendMeVoice.setDeliveryYn("N");				// 예약 발송일 경우 N				
				sendMeVoice.setReservationDate(reservationDate);			// 예약 발송일 경우 날짜				
				sendMeVoice.setReservationTime(reservationTime);			// 예약 발송일 경우 시각

				sendMeVoice.setFileName(fileName);				// 파일 명.	

				// 음성 파일.
				String fileChk = filePath;		// 경로 포함 파일 명

				File file = new File(fileChk);
				if(file.exists()){
					try {
						sendMeVoice.setFile(file);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				//				sendMeVoice.setFileContentType("audio/mpeg");			// FileContentType for mp3

				SendMeAudioMessageRest sendMeAudioMessageRest = new SendMeAudioMessageRest();
				SendMeVoice result = new SendMeVoice();
				result = sendMeAudioMessageRest.registerVoice2(sendMeVoice);	// 원본 registerVoice 이 에러가 발생하는 경우가 있어서 대체 사용.

				// 프로그레스 바를 감춘다.
				mHandler.sendMessage(mHandler.obtainMessage(THREAD_PROGRESS_BAR_INVISIBLE));

				// 인증번호 요청에 성공하면 toast 를 띄워서 알려준다. 
				if(("SUCCESS").equals(result.getResult())) {

					// 성공 알림 토스트
					// 예약 전송
					mHandler.sendMessage(mHandler.obtainMessage(THREAD_TOAST_RESERVATION_SEND_SUCCESS));

//					// 종료 프로세스
//					finishActivity();

//					// 키,벨류를 넣는다
//					extraBundle.putString("key1",  "val1");		 
					// 인텐트에 넣는다
					resultIntent.putExtras(extraBundle);
					callSetResult();
					
				}else{
					// 실패 알림 토스트
					mHandler.sendMessage(mHandler.obtainMessage(THREAD_TOAST_SEND_FAIL));
				}
			}
		});
		thread.start();
	}
	
	/**
	 * 로그를 남긴다	 
	 */
	public void threadRegisterLog() {
		Thread thread = new Thread(new Runnable() {
			public void run() {
				
				SendMeCommon sendMeCommon = new SendMeCommon();
				String nowTime = sendMeCommon.getCurrentDate();
				
				SendMeLog sendMeLog = new SendMeLog();
				sendMeLog.setPhoneNumber(sender);
				sendMeLog.setViewName(TAG);
				sendMeLog.setRegisterDate(nowTime);
				
				SendMeLogRest sendMeLogRest = new SendMeLogRest();
				
				sendMeLogRest.registerLog(sendMeLog);
			}
		});
		thread.start();
	}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	/**
	 * SharedPreference 정보를 확인 한다.
	 */
	public void confirmNotification() {
		SharedPreferences mSharedPreference = getSharedPreferences(SendMeConstant.SENDME_PREFERENCE, Activity.MODE_PRIVATE);

		sender = mSharedPreference.getString("phone_number", "");
		Log.i(TAG, "sender : " + sender);
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	
	// 액티비티 종료 관련 기능들

	public void callSetResult(){
		this.setResult(RESULT_OK, resultIntent);	// RESULT_OK 를 돌려주면 부모에서 받아 처리한다.
		finishActivity();
	}
	
	/**
	 * 뒤로 가기 버튼을 정의 한다.
	 * 화면을 종료 한다.
	 */
	@Override
	public void onBackPressed() {
		this.setResult(RESULT_CANCELED, resultIntent);
		finishActivity();
	}
	
	public void finishActivity(){
		sendMeActivityManager.removeActivity(SendMeAudioSendReservationActivity.this);
		finish();
	}
	
	@Override
	public void onResume(){
		super.onResume();
		dialog = ProgressDialog.show(SendMeAudioSendReservationActivity.this, "", "Send..", true);	// 제목, 내용
		dialog.hide();
	}
	@Override
	public void onStop(){
		super.onStop();
		dialog.dismiss();
	}
	
	
	
}

